
// Copyright (C) 2007 Richard Uhler
// This file is part of Esiply.
//
// Esiply is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License, Version 2,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#ifndef _BINARY_EXPRESSION_H_
#define _BINARY_EXPRESSION_H_

// This is a class for general binary expressions with the form
// that you have a left hand side, right hand side, and some
// operation to perform on them.

#include "Expression.h"

class BinaryExpression;

typedef Value*(BinaryExpression::*binary_operation_t)(Scope* scope) const;
typedef Value*(*binary_valueref_t)(Value* lhs, Value* rhs);

class BinaryExpression : public Expression
{
public:
    // We hereby take ownership of lhs, rhs. They must
    // have been new'ed, and no one else is allowed
    // to delete them. And no one else is allowed to 
    // trust their existance.
    BinaryExpression(binary_operation_t op, Expression* lhs, Expression* rhs);
    virtual Value* evaluate(Scope* scope);

    //  Here are all the binary operations.
    Value* add(Scope* scope) const;
    Value* add_assign(Scope* scope) const;
    Value* assign(Scope* scope) const;
    Value* bitwise_and(Scope* scope) const;
    Value* bitwise_and_assign(Scope* scope) const;
    Value* bitwise_or(Scope* scope) const;
    Value* bitwise_or_assign(Scope* scope) const;
    Value* bitwise_xor(Scope* scope) const;
    Value* bitwise_xor_assign(Scope* scope) const;
    Value* call(Scope* scope) const;
    Value* comma(Scope* scope) const;
    Value* construct(Scope* scope) const;
    Value* divide(Scope* scope) const;
    Value* divide_assign(Scope* scope) const;
    Value* equals(Scope* scope) const;
    Value* greater_than(Scope* scope) const;
    Value* greater_than_equal(Scope* scope) const;
    Value* in(Scope* scope) const;
    Value* instanceof(Scope* scope) const;
    Value* left_shift(Scope* scope) const;
    Value* left_shift_assign(Scope* scope) const;
    Value* less_than(Scope* scope) const;
    Value* less_than_equal(Scope* scope) const;
    Value* logical_and(Scope* scope) const;
    Value* logical_or(Scope* scope) const;
    Value* lookup(Scope* scope) const;
    Value* modulo(Scope* scope) const;
    Value* modulo_assign(Scope* scope) const;
    Value* multiply(Scope* scope) const;
    Value* multiply_assign(Scope* scope) const;
    Value* not_equals(Scope* scope) const;
    Value* right_shift(Scope* scope) const;
    Value* right_shift_assign(Scope* scope) const;
    Value* strict_equals(Scope* scope) const;
    Value* strict_not_equals(Scope* scope) const;
    Value* subtract(Scope* scope) const;
    Value* subtract_assign(Scope* scope) const;
    Value* unsigned_right_shift(Scope* scope) const;
    Value* unsigned_right_shift_assign(Scope* scope) const;

private:
    // A helper function for the assignment operators.
    Value* assign(Scope* scope, binary_valueref_t op) const;

    // A helper function for typical value operations.
    Value* operate(Scope* scope, binary_valueref_t op) const;

    binary_operation_t m_op;
    Expression* m_lhs;
    Expression* m_rhs;
};

#endif//_BINARY_EXPRESSION_H_

